function calcularGradosHoraCosenoidalOptimizado() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var datosUsuariosSheet = ss.getSheetByName("datos usuarios");
  var datosSheet = ss.getSheetByName("Hoja 1");
  var gradosDiaSheet = ss.getSheetByName("Grados Día") || ss.insertSheet("Grados Día");

  if (!datosUsuariosSheet || !datosSheet) {
    Logger.log("Las hojas necesarias no están disponibles.");
    return;
  }

  var datosUsuarios = datosUsuariosSheet.getDataRange().getValues();
  var datos = datosSheet.getDataRange().getValues();

  // Mapeo de sensores
  var sensores = {};
  for (var i = 1; i < datosUsuarios.length; i++) {
    var nombreSensor = (datosUsuarios[i][0] || "").toString().trim();
    var Tb = parseFloat(datosUsuarios[i][7]);
    var Tu = parseFloat(datosUsuarios[i][8]);

    if (nombreSensor && !isNaN(Tb) && !isNaN(Tu) && Tu !== Tb) {
      sensores[nombreSensor] = { Tb, Tu };
    }
  }

  var acumulados = {};

  for (var i = 1; i < datos.length; i++) {
    var nombreSensor = (datos[i][2] || "").toString().trim();
    var fechaHora = datos[i][1];
    var tempRaw = (datos[i][4] || "").toString().replace(",", ".");
    var temperatura = parseFloat(tempRaw);

    if (!(fechaHora instanceof Date)) continue;
    if (!sensores[nombreSensor]) continue;
    if (isNaN(temperatura)) continue;

    var { Tb, Tu } = sensores[nombreSensor];
    var fecha = Utilities.formatDate(fechaHora, "GMT+1", "dd/MM/yyyy");

    var clave = `${nombreSensor}|${fecha}`;
    var x = (temperatura - Tb) / (Tu - Tb);

    // Asegurar que x está entre 0 y 1
    x = Math.max(0, Math.min(1, x));

    var gradosHora = ((Tu - Tb) / 2) * (1 + Math.cos(Math.PI + Math.PI * x));
    gradosHora = Math.max(0, gradosHora);

    if (!acumulados[clave]) {
      acumulados[clave] = { suma: 0, conteo: 0 };
    }

    acumulados[clave].suma += gradosHora;
    acumulados[clave].conteo += 1;
  }

  // Escribir resultados
  var salida = [["Sensor", "Fecha", "Grados Día"]];
  for (var clave in acumulados) {
    var [sensor, fecha] = clave.split("|");
    var total = acumulados[clave].suma;
    var count = acumulados[clave].conteo;
    var promedio = total / count;
    salida.push([sensor, fecha, promedio]);
  }

  gradosDiaSheet.clear();
  gradosDiaSheet.getRange(1, 1, salida.length, salida[0].length).setValues(salida);
}